//
//  WJTouchID2.m
//  WJTouchIDExample
//
//  Created by bringbird on 16/1/13.
//  Copyright © 2016年 韦明杰 All rights reserved.

//  QQ:6799400 Email:bringbird@163.com.


#import "WJTouchID.h"
#import <LocalAuthentication/LocalAuthentication.h>

#define SYSTEM_VERSION_EQUAL_TO(v)                  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedSame)
#define SYSTEM_VERSION_GREATER_THAN(v)              ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedDescending)
#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v)  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN(v)                 ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(v)     ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedDescending)


@interface WJTouchID ()

@end

@implementation WJTouchID

static WJTouchID *touchID;

+ (instancetype)touchID {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        touchID = [[self alloc]init];
    });
    return touchID;
}

- (void)startWJTouchIDWithMessage:(NSString *)message fallbackTitle:(NSString *)fallbackTitle policy:(LAPolicy)policy delegate:(id<WJTouchIDDelegate>)delegate
{
    NSAssert(delegate != nil, WJNotice(@"WJTouchIDDelegate 不能为空", @"WJTouchIDDelegate must be non-nil"));
    
    LAContext *context = [[LAContext alloc]init];
    context.localizedFallbackTitle = fallbackTitle;
    NSError *error = nil;
    self.delegate = delegate;
    
//    context.localizedCancelTitle   iOS10 以后增加，默认为“取消”
    
    /**
     context.evaluatedPolicyDomainState iOS9 以后增加，
     
     此属性仅在调用评估策略和成功的Touch ID身份验证时设置，或者当canEvaluatePolicy成功执行生物识别策略时。
     它在所有其他情况下都是空的。
     如果手指数据库修改(手指被添加或删除),evaluatedPolicyDomainState数据将会改变。自然这样的数据库更改不能确定但是比较不同evaluatePolicy evaluatedPolicyDomainState后的数据将揭示事实数据库调用之间的变化。
     请注意，此属性返回的值也可以在OS版本之间更改，即使没有更改注册的指纹。
     */
    
    /**
     touchIDAuthenticationAllowableReuseDuration iOS9 以后增加
     
     接受一个成功的Touch ID设备的时间间隔(在锁屏上)。
     这个属性可以在秒内设置一个时间间隔。如果该设备在这个时间间隔内通过Touch ID成功解锁，那么在此上下文中触摸ID身份验证将自动成功，并在不提示用户使用Touch ID的情况下调用应答块。
     默认值为0，这意味着之前没有任何TouchID解锁可以被重用。
     他的属性仅用于从设备锁屏幕中重新使用Touch ID匹配。
     它不允许在应用程序或应用程序之间重用以前的Touch ID匹配。
     最大支持时间间隔为5分钟，设置超过5分钟的值并不会增加被接受的时间间隔。
     
     这个属性应该是类似于支付宝的指纹开启应用，如果你打开他解锁之后，按Home键返回桌面，再次进入支付宝是不需要录入指纹的。因为这个属性可以设置一个时间间隔，在时间间隔内是不需要再次录入。默认是0秒，最长可以设置5分钟。
     */
    if (SYSTEM_VERSION_LESS_THAN(@"9")) {//低于iOS9
        policy  =   kLAPolicyDeviceOwnerAuthenticationWithBiometrics;
    }
    
    if ([context canEvaluatePolicy:policy error:&error]) {
        NSLog(@"context.evaluatedPolicyDomainState=%@",context.evaluatedPolicyDomainState);
        
        [context evaluatePolicy:policy localizedReason:message == nil ? WJNotice(@"自定义信息", @"The Custom Message") : message reply:^(BOOL success, NSError * _Nullable error) {
            
            if (success) {
                if ([self.delegate respondsToSelector:@selector(WJTouchIDAuthorizeSuccess)]) {
                    [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                        [self.delegate WJTouchIDAuthorizeSuccess];
                    }];
                }
            } else if (error) {
                
                switch (error.code) {
                        
                    case LAErrorAuthenticationFailed: {// -1 连续三次指纹识别错误
                        
                        if ([self.delegate respondsToSelector:@selector(WJTouchIDAuthorizeFailure)]) {
                            [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                                [self.delegate WJTouchIDAuthorizeFailure];
                            }];
                        }
                    }
                        break;
                        
                    case LAErrorUserCancel: {//-2 在TouchID对话框中点击了取消按钮
                        
                        if ([self.delegate respondsToSelector:@selector(WJTouchIDAuthorizeErrorUserCancel)]) {
                            [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                                [self.delegate WJTouchIDAuthorizeErrorUserCancel];
                            }];
                        }
                    }
                        break;
                        
                    case LAErrorUserFallback: {//-3 在TouchID对话框中点击了输入密码按钮
                        
                        if ([self.delegate respondsToSelector:@selector(WJTouchIDAuthorizeErrorUserFallback)]) {
                            [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                                [self.delegate WJTouchIDAuthorizeErrorUserFallback];
                            }];
                        }
                    }
                        break;
                        
                    case LAErrorSystemCancel:{// -4 TouchID对话框被系统取消，例如按下Home或者电源键
                        
                        if ([self.delegate respondsToSelector:@selector(WJTouchIDAuthorizeErrorSystemCancel)]) {
                            [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                                [self.delegate WJTouchIDAuthorizeErrorSystemCancel];
                            }];
                        }
                    }
                        break;
                        
                    case LAErrorPasscodeNotSet: {//-5 设备系统未设置密码
                        
                        if ([self.delegate respondsToSelector:@selector(WJTouchIDAuthorizeErrorPasscodeNotSet)]) {
                            [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                                [self.delegate WJTouchIDAuthorizeErrorPasscodeNotSet];
                            }];
                        }
                    }
                        break;
                        
                    case LAErrorTouchIDNotAvailable: {//-6,设备未设置Touch ID
                        
                        if ([self.delegate respondsToSelector:@selector(WJTouchIDAuthorizeErrorTouchIDNotAvailable)]) {
                            [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                                [self.delegate WJTouchIDAuthorizeErrorTouchIDNotAvailable];
                            }];
                        }
                    }
                        break;
                        
                    case LAErrorTouchIDNotEnrolled: {//-7,用户未录入指纹
                        
                        if ([self.delegate respondsToSelector:@selector(WJTouchIDAuthorizeErrorTouchIDNotEnrolled)]) {
                            [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                                [self.delegate WJTouchIDAuthorizeErrorTouchIDNotEnrolled];
                            }];
                        }
                    }
                        break;
                    case LAErrorTouchIDLockout: {//-8 连续五次指纹识别错误，TouchID功能被锁定，下一次需要输入系统密码
                        
                        if ([self.delegate respondsToSelector:@selector(WJTouchIDAuthorizeErrorTouchIDLockout)]) {
                            [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                                [self.delegate WJTouchIDAuthorizeErrorTouchIDLockout];
                            }];
                        }
                    }
                        break;
                        
                    case LAErrorAppCancel:  {   //-9,用户不能控制情况下APP被挂起,如突然来了电话，电话应用进入前台，APP被挂起啦
                        
                        if ([self.delegate respondsToSelector:@selector(WJTouchIDAuthorizeErrorAppCancel)]) {
                            [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                                [self.delegate WJTouchIDAuthorizeErrorAppCancel];
                            }];
                        }
                    }
                        break;
                        
                    case LAErrorInvalidContext: {   //-10,LAContext传递给这个调用之前已经失效
                        
                        if ([self.delegate respondsToSelector:@selector(WJTouchIDAuthorizeErrorInvalidContext)]) {
                            [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                                [self.delegate WJTouchIDAuthorizeErrorInvalidContext];
                            }];
                        }
                    }
                        break;
                }
            }
        }];
        
    } else {
        if(error.code==-8){
            if ([self.delegate respondsToSelector:@selector(WJTouchIDAuthorizeErrorTouchIDLockout)]) {
                [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                    [self.delegate WJTouchIDAuthorizeErrorTouchIDLockout];
                }];
            }
        }else{
            if ([self.delegate respondsToSelector:@selector(WJTouchIDIsNotSupport)]) {
                [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                    [self.delegate WJTouchIDIsNotSupport];
                }];
            }
        }
    }
}
@end
